package helper

import (
	"fmt"
	"strconv"
	"strings"

	"mall/service/blog/rpc/blogclient"
	"mall/service/layout/rpc/layout"
	"mall/service/setting/rpc/setting"
	"mall/service/wpgql/api/internal/graph/model"
	"mall/service/wpgql/api/internal/graph/util"

	"github.com/sirupsen/logrus"
)

func BlogGeneralSettingsToGraphQL(settings []*setting.SettingDetailResponse) *model.GeneralSettings {
	resp := &model.GeneralSettings{}

	if settings == nil || len(settings) == 0 {
		return resp
	}

	for _, setting := range settings {
		switch setting.Name {
		case "date_format":
			resp.DateFormat = &setting.Value
		case "blogdescription":
			resp.Description = &setting.Value
		case "admin_email":
			resp.Email = &setting.Value
		case "WPLANG":
			resp.Language = &setting.Value
		case "start_of_week":
			if startOfWeek, err := strconv.Atoi(setting.Value); err == nil {
				resp.StartOfWeek = &startOfWeek
			}
		case "time_format":
			resp.TimeFormat = &setting.Value
		case "timezone_string":
			resp.Timezone = &setting.Value
		case "blogname":
			resp.Title = &setting.Value
		case "siteurl":
			resp.URL = &setting.Value
		}
	}

	return resp
}

func BlogLayoutMenuIDToGraphQL(v int64) string {
	return util.Int64IDToGraphQL(v, util.RpcEntityNames.BlogLayoutMenu)
}

func BlogLayoutMenuToGraphQL(menu *layout.MenuDetailResponse) *model.Menu {
	if menu == nil {
		return &model.Menu{}
	}

	var (
		count        int
		databaseID   int
		id           string
		isRestricted bool
		locations    []*model.MenuLocationEnum
		menuItems    *model.MenuToMenuItemConnection
		name         string
		slug         string
	)

	count = int(menu.Count)
	if menu.Id > 0 {
		databaseID = int(menu.Id)
		id = BlogLayoutMenuIDToGraphQL(menu.Id)
	}
	name = menu.Name
	slug = menu.Slug

	if len(menu.MenuItem) > 0 {
		var items []*model.MenuItem
		for _, menuItem := range menu.MenuItem {
			items = append(items, BlogLayoutMenuItemToGraphQL(menuItem))
		}
		menuItems = GetBlogMenuToMenuItemConnection(items, false, false, -1, false)
	}

	return &model.Menu{
		Count:        &count,
		DatabaseID:   databaseID,
		ID:           id,
		IsRestricted: &isRestricted,
		Locations:    locations,
		MenuItems:    menuItems,
		Name:         &name,
		Slug:         &slug,
	}
}

func BlogLayoutMenuItemIDToGraphQL(v int64) string {
	return util.Int64IDToGraphQL(v, util.RpcEntityNames.BlogLayoutMenuItem)
}

func BlogLayoutMenuItemToGraphQL(menuItem *layout.MenuItemDetailResponse) *model.MenuItem {
	if menuItem == nil {
		return &model.MenuItem{}
	}

	var (
		databaseId       int
		description      string
		id               string
		isRestricted     bool
		label            string
		linkRelationship string
		order            int
		parentDatabaseId int
		parentId         string
		path             string
		target           string
		title            string
		url              string
	)

	if menuItem.Id > 0 {
		databaseId = int(menuItem.Id)
		id = BlogLayoutMenuItemIDToGraphQL(menuItem.Id)
	}
	if menuItem.Order > 0 {
		order = int(menuItem.Order)
	}
	if menuItem.ParentId > 0 {
		parentDatabaseId = int(menuItem.ParentId)
		parentId = BlogLayoutMenuItemIDToGraphQL(menuItem.ParentId)
	}
	target = menuItem.Target
	title = menuItem.Title
	url = menuItem.Link
	label = menuItem.Title
	path = menuItem.Link

	return &model.MenuItem{
		DatabaseID:       databaseId,
		Description:      &description,
		ID:               id,
		IsRestricted:     &isRestricted,
		Label:            &label,
		LinkRelationship: &linkRelationship,
		Order:            &order,
		ParentDatabaseID: &parentDatabaseId,
		ParentID:         &parentId,
		Path:             &path,
		Target:           &target,
		Title:            &title,
		URL:              &url,
	}
}

func BlogAuthorIDToGraphQL(v int64) string { ////
	return util.Int64IDToGraphQL(v, util.RpcEntityNames.BlogAuthor)
}

func BlogAuthorWithID(id int64) *model.NodeWithAuthorToUserConnectionEdge {
	return &model.NodeWithAuthorToUserConnectionEdge{
		Node: &model.User{
			ID: BlogAuthorIDToGraphQL(id),
		},
	}
}

func BlogAuthorToGraphQL(author *blogclient.BlogAuthor) *model.NodeWithAuthorToUserConnectionEdge {
	if author == nil {
		return &model.NodeWithAuthorToUserConnectionEdge{}
	}

	var (
		id        string
		name      string
		authorUrl string
	)
	if author.Id > 0 {
		id = BlogAuthorIDToGraphQL(author.Id)
	}
	if author.Name != "" {
		name = author.Name
	}
	if author.Url != "" {
		authorUrl = author.Url
	}

	r := &model.NodeWithAuthorToUserConnectionEdge{
		Node: &model.User{
			ID:   id,
			Name: &name,
			Avatar: &model.Avatar{
				URL: &authorUrl,
			},
		},
	}

	return r
}

func BlogCategoryIDToGraphQL(v int64) string {
	return util.Int64IDToGraphQL(v, util.RpcEntityNames.BlogCategory)
}

func BlogCategoryToGraphQL(category *blogclient.BlogCategory) *model.Category {
	if category == nil {
		return &model.Category{}
	}

	var (
		databaseId int
		id         string
		name       string
		slug       string
		uri        string
	)

	if category.Id > 0 {
		databaseId = int(category.Id)
		id = BlogCategoryIDToGraphQL(category.Id)
	}
	name = category.Name
	slug = category.Slug
	uri  = category.Uri

	r := &model.Category{
		DatabaseID: databaseId,
		ID:         id,
		Name:       &name,
		Slug:       &slug,
		URI:        &uri,
	}

	return r
}

func BlogSectionIDToGraphQL(v int64) string {
	return util.Int64IDToGraphQL(v, util.RpcEntityNames.BlogSection)
}

func BlogSectionToGraphQL(section *blogclient.BlogCategory) *model.Section {
	if section == nil {
		return &model.Section{}
	}

	var (
		databaseId int
		id         string
		name       string
		slug       string
		uri        string
	)

	if section.Id > 0 {
		databaseId = int(section.Id)
		id = BlogSectionIDToGraphQL(section.Id)
	}
	name = section.Name
	slug = section.Slug
	uri  = section.Uri

	r := &model.Section{
		DatabaseID: databaseId,
		ID:         id,
		Name:       &name,
		Slug:       &slug,
		URI:        &uri,
	}

	return r
}

func BlogTagIDToGraphQL(v int64) string {
	return util.Int64IDToGraphQL(v, util.RpcEntityNames.BlogTag)
}

func BlogTagToGraphQL(tag *blogclient.BlogTag) *model.Tag {
	if tag == nil {
		return &model.Tag{}
	}

	var (
		databaseId int
		id         string
		name       string
		slug       string
		uri        string
	)

	if tag.Id > 0 {
		databaseId = int(tag.Id)
		id = BlogTagIDToGraphQL(tag.Id)
	}
	name = tag.Name
	slug = tag.Slug
	uri  = tag.Uri

	r := &model.Tag{
		DatabaseID: databaseId,
		ID:         id,
		Name:       &name,
		Slug:       &slug,
		URI:        &uri,
	}

	return r
}

func BlogMediaIDToGraphQL(v int64) string {
	return util.Int64IDToGraphQL(v, util.RpcEntityNames.BlogMedia)
}

func BlogMediaToGraphQL(mediaItem *blogclient.BlogMedia) *model.MediaItem {
	if mediaItem == nil {
		return &model.MediaItem{}
	}

	var (
		databaseId int
		id         string
		url        string
		altText    string
		width      int
		height     int
	)

	if mediaItem.Uid > 0 {
		databaseId = int(mediaItem.Uid)
		id = BlogMediaIDToGraphQL(mediaItem.Uid)
	}
	url = mediaItem.Url
	altText = mediaItem.AltText
	if mediaItem.Meta != "" {
		meta := strings.Split(mediaItem.Meta, arrayKeyValueSeparator)
		if len(meta) > 0 {
			for _, metaItem := range meta {
				detailItems := strings.SplitN(metaItem, keyValueSeparator, 2)
				if len(detailItems) == 2 && detailItems[0] == "width" {
					if i, err := strconv.Atoi(detailItems[1]); err == nil {
						width = i
					}
				}
				if len(detailItems) == 2 && detailItems[0] == "height" {
					if i, err := strconv.Atoi(detailItems[1]); err == nil {
						height = i
					}
				}
			}
		}
	}

	return &model.MediaItem{
		AltText:      &altText,
		DatabaseID:   databaseId,
		ID:           id,
		MediaItemURL: &url,
		SourceURL:    &url,
		MediaDetails: &model.MediaDetails{
			Height: &height,
			Width:  &width,
		},
	}
}

func BlogSeoSettingsFromMeta(meta []*blogclient.BlogMeta) *model.SeoSettings {
	var fullHead string
	var title string
	var metaDesc string
	for _, metaItem := range meta {
		switch metaItem.Key {
		case "fullHead":
			fullHead = metaItem.Value
		case "title":
			title = metaItem.Value
		case "metaDesc":
			metaDesc = metaItem.Value
		}
	}

	return &model.SeoSettings{
		FullHead: &fullHead,
		Title:    &title,
		MetaDesc: &metaDesc,
	}
}

func BlogPostIDToGraphQL(v int64) string {
	return util.Int64IDToGraphQL(v, util.RpcEntityNames.BlogPost)
}

func BlogPostToGraphQL(post *blogclient.PostDetailResponse) *model.Post {
	if post == nil {
		return &model.Post{}
	}

	var (
		authorDatabaseId int
		authorId         string
		databaseId       int
		id               string
		title            string
		excerpt          string
		status           string
		commentStatus    string
		slug             string
		uri              string
		link             string
		date             string
		dateGmt          string
		modified         string
		modifiedGmt      string
		commentCount     int
		content          string
	)

	if post.Id > 0 {
		databaseId = int(post.Id)
		id = BlogPostIDToGraphQL(post.Id)
	}
	if post.AuthorId > 0 {
		authorDatabaseId = int(post.AuthorId)
		authorId = BlogAuthorIDToGraphQL(post.AuthorId)
	}
	title = post.Title
	excerpt = post.Excerpt
	status = post.StatusText
	commentStatus = post.CommentStatusText
	slug = post.Slug
	uri = post.Uri
	link = post.Link
	date = post.Date
	dateGmt = post.DateGmt
	modified = post.Modified
	modifiedGmt = post.ModifiedGmt
	commentCount = int(post.CommentCount)
	content = post.ContentHtml

	r := &model.Post{
		AuthorDatabaseID: &authorDatabaseId,
		AuthorID:         &authorId,
		CommentCount:     &commentCount,
		CommentStatus:    &commentStatus,
		Content:          &content,
		DatabaseID:       databaseId,
		Date:             &date,
		DateGmt:          &dateGmt,
		Excerpt:          &excerpt,
		ID:               id,
		Link:             &link,
		Modified:         &modified,
		ModifiedGmt:      &modifiedGmt,
		Slug:             &slug,
		Status:           &status,
		Title:            &title,
		URI:              &uri,
	}

	if util.Int64IsFilled(post.AuthorId) {
		if post.Author != nil {
			r.Author = BlogAuthorToGraphQL(post.Author)
		} else {
			r.Author = BlogAuthorWithID(post.AuthorId)
		}
	}
	if len(post.Categories) > 0 {
		var categories []*model.Category
		for _, category := range post.Categories {
			categories = append(categories, BlogCategoryToGraphQL(category))
		}
		r.Categories = GetPostToCategoryConnection(categories, false, false, 0, false)
	}
	if len(post.Tags) > 0 {
		var tags []*model.Tag
		for _, tag := range post.Tags {
			tags = append(tags, BlogTagToGraphQL(tag))
		}
		r.Tags = GetPostToTagConnection(tags, false, false, 0, false)
	}
	if len(post.Media) > 0 {
		mediaItem := BlogMediaToGraphQL(post.Media[0])
		r.FeaturedImage = &model.NodeWithFeaturedImageToMediaItemConnectionEdge{
			Node: mediaItem,
		}
	}
	if len(post.Meta) > 0 {
		r.Seo = BlogSeoSettingsFromMeta(post.Meta)
	}

	return r
}

func BlogPageIDToGraphQL(v int64) string {
	return util.Int64IDToGraphQL(v, util.RpcEntityNames.BlogPage)
}

func BlogPageToGraphQL(page *blogclient.PageDetailResponse) *model.Page {
	if page == nil {
		return &model.Page{}
	}

	var (
		authorDatabaseId int
		authorId         string
		databaseId       int
		id               string
		parentDatabaseId int
		parentId         string
		title            string
		status           string
		commentStatus    string
		slug             string
		uri              string
		link             string
		date             string
		dateGmt          string
		modified         string
		modifiedGmt      string
		commentCount     int
		menuOrder        int
		content          string
	)

	if page.Id > 0 {
		databaseId = int(page.Id)
		id = BlogPageIDToGraphQL(page.Id)
	}
	if page.AuthorId > 0 {
		authorDatabaseId = int(page.AuthorId)
		authorId = BlogAuthorIDToGraphQL(page.AuthorId)
	}
	if page.ParentId > 0 {
		parentDatabaseId = int(page.ParentId)
		parentId = BlogPageIDToGraphQL(page.ParentId)
	}
	title  = page.Title
	status = page.StatusText
	commentStatus = page.CommentStatusText
	slug = page.Slug
	uri = page.Uri
	link = page.Link
	date = page.Date
	dateGmt = page.DateGmt
	modified = page.Modified
	modifiedGmt = page.ModifiedGmt
	commentCount = int(page.CommentCount)
	menuOrder = int(page.SortOrder)
	content = page.ContentHtml

	r := &model.Page{
		AuthorDatabaseID: &authorDatabaseId,
		AuthorID:         &authorId,
		CommentCount:     &commentCount,
		CommentStatus:    &commentStatus,
		Content:          &content,
		DatabaseID:       databaseId,
		Date:             &date,
		DateGmt:          &dateGmt,
		ID:               id,
		Link:             &link,
		MenuOrder:        &menuOrder,
		Modified:         &modified,
		ModifiedGmt:      &modifiedGmt,
		ParentDatabaseID: &parentDatabaseId,
		ParentID:         &parentId,
		Slug:             &slug,
		Status:           &status,
		Title:            &title,
		URI:              &uri,
	}

	if util.Int64IsFilled(page.AuthorId) {
		if page.Author != nil {
			r.Author = BlogAuthorToGraphQL(page.Author)
		} else {
			r.Author = BlogAuthorWithID(page.AuthorId)
		}
	}
	if len(page.Media) > 0 {
		mediaItem := BlogMediaToGraphQL(page.Media[0])
		r.FeaturedImage = &model.NodeWithFeaturedImageToMediaItemConnectionEdge{
			Node: mediaItem,
		}
	}
	if len(page.Meta) > 0 {
		r.Seo = BlogSeoSettingsFromMeta(page.Meta)
	}

	return r
}

func BlogBookIDToGraphQL(v int64) string {
	return util.Int64IDToGraphQL(v, util.RpcEntityNames.BlogBook)
}

func BlogEntryToGraphQL(entry *blogclient.BlogEntry) *model.Book {
	if entry == nil {
		return &model.Book{}
	}

	var (
		databaseId int
		id         string
		title      string
		slug       string
		uri        string
	)

	if entry.Id > 0 {
		databaseId = int(entry.Id)
		id = BlogBookIDToGraphQL(entry.Id)
	}
	title = entry.Title
	// entry.Excerpt
	slug = entry.Slug
	// entry.Url // 图片链接
	uri = entry.Link // 固定链接
	// entry.SectionId // 词条分类
	// entry.Section // 词条名
	// entry.GroupId // 分组
	// entry.Order // 排序
	// entry.Meta string

	r := &model.Book{
		DatabaseID: databaseId,
		ID:         id,
		Slug:       &slug,
		Title:      &title,
		URI:        &uri,
	}

	if entry.SectionId > 0 {
		var groupId int
		groupId = int(entry.GroupId)
		node := &model.Section{
			DatabaseID:  int(entry.SectionId),
			ID:          BlogSectionIDToGraphQL(entry.SectionId),
			Name:        &entry.Section,
			TermGroupID: &groupId,
		}
		r.Sections = &model.BookToSectionConnection{
			Nodes: []*model.Section{node},
		}
	}

	if entry.Url != "" {
		var (
			altText string
			url     string
			width   int
			height  int
		)
		altText = entry.Slug
		url = entry.Url
		if entry.Meta != "" {
			meta := strings.Split(entry.Meta, arrayKeyValueSeparator)
			if len(meta) > 0 {
				for _, metaItem := range meta {
					detailItems := strings.SplitN(metaItem, keyValueSeparator, 2)
					if len(detailItems) == 2 && detailItems[0] == "width" {
						if i, err := strconv.Atoi(detailItems[1]); err == nil {
							width = i
						}
					}
					if len(detailItems) == 2 && detailItems[0] == "height" {
						if i, err := strconv.Atoi(detailItems[1]); err == nil {
							height = i
						}
					}
				}
			}
		}
		mediaItem := &model.MediaItem{
			AltText:      &altText,
			MediaItemURL: &url,
			SourceURL:    &url,
			MediaDetails: &model.MediaDetails{
				Height: &height,
				Width:  &width,
			},
		}
		r.FeaturedImage = &model.NodeWithFeaturedImageToMediaItemConnectionEdge{
			Node: mediaItem,
		}
	}

	return r
}

func BlogBookToGraphQL(entry *blogclient.BookDetailResp) *model.Book {
	if entry == nil {
		return &model.Book{}
	}

	var (
		databaseId       int
		id               string
		title            string
		status           string
		commentStatus    string
		slug             string
		uri              string
		link             string
		date             string
		dateGmt          string
		modified         string
		modifiedGmt      string
		commentCount     int
		content          string
	)

	if entry.Id > 0 {
		databaseId = int(entry.Id)
		id = BlogBookIDToGraphQL(entry.Id)
	}
	title  = entry.Title
	status = entry.StatusText
	commentStatus = entry.CommentStatusText
	slug = entry.Slug
	uri = entry.Uri
	link = entry.Link
	date = entry.Date
	dateGmt = entry.DateGmt
	modified = entry.Modified
	modifiedGmt = entry.ModifiedGmt
	commentCount = int(entry.CommentCount)
	content = entry.ContentHtml

	r := &model.Book{
		CommentCount:  &commentCount,
		CommentStatus: &commentStatus,
		Content:       &content,
		DatabaseID:    databaseId,
		Date:          &date,
		DateGmt:       &dateGmt,
		ID:            id,
		Link:          &link,
		Modified:      &modified,
		ModifiedGmt:   &modifiedGmt,
		Slug:          &slug,
		Status:        &status,
		Title:         &title,
		URI:           &uri,
	}

	if len(entry.Categories) > 0 {
		logrus.Info(fmt.Sprintf("BlogBookToGraphQL Categories : %+v ", entry.Categories))
		var categories []*model.Category
		for _, category := range entry.Categories {
			categories = append(categories, BlogCategoryToGraphQL(category))
		}
		r.Categories = GetBookToCategoryConnection(categories, false, false, 0, false)
	}
	if len(entry.Tags) > 0 {
		logrus.Info(fmt.Sprintf("BlogBookToGraphQL Tags : %+v ", entry.Tags))
		var tags []*model.Tag
		for _, tag := range entry.Tags {
			tags = append(tags, BlogTagToGraphQL(tag))
		}
		r.Tags = GetBookToTagConnection(tags, false, false, 0, false)
	}
	if len(entry.Sections) > 0 {
		var sections []*model.Section
		for _, section := range entry.Sections {
			sections = append(sections, BlogSectionToGraphQL(section))
		}
		r.Sections = GetBookToSectionConnection(sections, false, false, 0, false)
	}
	if len(entry.Media) > 0 {
		mediaItem := BlogMediaToGraphQL(entry.Media[0])
		r.FeaturedImage = &model.NodeWithFeaturedImageToMediaItemConnectionEdge{
			Node: mediaItem,
		}
	}
	if len(entry.Meta) > 0 {
		// logrus.Info(fmt.Sprintf("BlogBookToGraphQL Meta : %+v ", entry.Meta))
		r.Seo = BlogSeoSettingsFromMeta(entry.Meta)
	}
	if len(entry.Relations) > 0 {
		// logrus.Info(fmt.Sprintf("BlogBookToGraphQL Relations : %+v ", entry.Relations))
		var relations []*model.Book
		for _, relation := range entry.Relations {
			relations = append(relations, BlogEntryToGraphQL(relation))
		}
		r.Relations = GetBookToRelationConnection(relations, false, false, 0, false)
	}

	return r
}
